<template>
  <ElPopover
    placement="bottom-start"
    trigger="click"
    width="260"
    :popper-style="{ overflow: 'auto', maxHeight: '500px' }"
    :show-arrow="false">
    <template #reference>
      <ElButton>
        <template #icon>
          <i
            style="cursor: pointer;"
            class="iconfont icon-BarsOutlined" />
        </template>
      </ElButton>
    </template>
    <div class="content">
      <div class="header">
        <ElCheckbox
          v-model="checkAll"
          :indeterminate="isIndeterminate"
          @change="handleCheckAllChange">
          列展示
        </ElCheckbox>
        <ElButton
          link
          type="primary"
          @click="handleReset">
          重置
        </ElButton>
      </div>
      <div class="setting-list">
        <div class="list left-fixed">
          <p>固定在左侧</p>
          <ElCheckboxGroup
            v-model="leftFixedChecked"
            style="display: flex; flex-direction: column;"
            @change="handleLeftFixedCheckedChange">
            <ElCheckbox
              v-for="(item, index) in leftFixedOptions"
              :key="index"
              :draggable="true"
              :label="item.label"
              :value="item.label"
              @dragstart="handleDragStart(item.label)"
              @dragover.prevent
              @drop="handleDrop(item.label)">
              <template #default>
                <div
                  class="list__item"
                  @mouseenter="handleMouseenter(leftFixedOptionsShowAction, index)"
                  @mouseleave="handleMouseLeave(leftFixedOptionsShowAction, index)">
                  <div>{{ item.label }}</div>
                  <div
                    v-show="leftFixedOptionsShowAction[index]"
                    class="action">
                    <ElTooltip
                      content="不固定"
                      placement="top">
                      <i
                        style="cursor: pointer;"
                        class="iconfont icon-VerticalAlignMiddleOutlined"
                        @click.prevent="handleNoFixed(item)" />
                    </ElTooltip>
                    <ElTooltip
                      content="固定到列尾"
                      placement="top">
                      <i
                        style="cursor: pointer;"
                        class="iconfont icon-VerticalAlignBottomOutlined"
                        @click.prevent="handleRightFixed(item)" />
                    </ElTooltip>
                  </div>
                </div>
              </template>
            </ElCheckbox>
          </ElCheckboxGroup>
        </div>
        <div class="list no-fixed">
          <p>不固定</p>
          <ElCheckboxGroup
            v-model="noFixedChecked"
            style="display: flex; flex-direction: column;"
            @change="handleNoFixedCheckedChange">
            <ElCheckbox
              v-for="(item, index) in noFixedOptions"
              :key="index"
              :draggable="true"
              :label="item.label"
              :value="item.label"
              @dragstart="handleDragStart(item.label)"
              @dragover.prevent
              @drop="handleDrop(item.label)">
              <template #default>
                <div
                  class="list__item"
                  @mouseenter="handleMouseenter(noFixedOptionsShowAction, index)"
                  @mouseleave="handleMouseLeave(noFixedOptionsShowAction, index)">
                  <div>{{ item.label }}</div>
                  <div
                    v-show="noFixedOptionsShowAction[index]"
                    class="action">
                    <ElTooltip
                      content="固定到列首"
                      placement="top">
                      <i
                        style="cursor: pointer;"
                        class="iconfont icon-VerticalAlignTopOutlined"
                        @click.prevent="handleLeftFixed(item)" />
                    </ElTooltip>
                    <ElTooltip
                      content="固定到列尾"
                      placement="top">
                      <i
                        style="cursor: pointer;"
                        class="iconfont icon-VerticalAlignBottomOutlined"
                        @click.prevent="handleRightFixed(item)" />
                    </ElTooltip>
                  </div>
                </div>
              </template>
            </ElCheckbox>
          </ElCheckboxGroup>
        </div>
        <div class="list right-fixed">
          <p>固定在右侧</p>
          <ElCheckboxGroup
            v-model="rightFixedChecked"
            style="display: flex; flex-direction: column;"
            @change="handleRightFixedCheckedChange">
            <ElCheckbox
              v-for="(item, index) in rightFixedOptions"
              :key="index"
              :draggable="true"
              :label="item.label"
              :value="item.label"
              @dragstart="handleDragStart(item.label)"
              @dragover.prevent
              @drop="handleDrop(item.label)">
              <template #default>
                <div
                  class="list__item"
                  @mouseenter="handleMouseenter(rightFixedOptionsShowAction, index)"
                  @mouseleave="handleMouseLeave(rightFixedOptionsShowAction, index)">
                  <div>{{ item.label }}</div>
                  <div
                    v-show="rightFixedOptionsShowAction[index]"
                    class="action">
                    <ElTooltip
                      content="固定到列首"
                      placement="top">
                      <i
                        style="cursor: pointer;"
                        class="iconfont icon-VerticalAlignTopOutlined"
                        @click.prevent="handleLeftFixed(item)" />
                    </ElTooltip>
                    <ElTooltip
                      content="不固定"
                      placement="top">
                      <i
                        style="cursor: pointer;"
                        class="iconfont icon-VerticalAlignMiddleOutlined"
                        @click.prevent="handleNoFixed(item)" />
                    </ElTooltip>
                  </div>
                </div>
              </template>
            </ElCheckbox>
          </ElCheckboxGroup>
        </div>
      </div>
    </div>
  </ElPopover>
</template>

<script setup>
import { computed, ref } from 'vue'

const props = defineProps({
  tableAllOptions: Array,
  initTableOptions: Array,
})
const emits = defineEmits(['updateTableOptions'])

const tableAllOptions = ref(props.tableAllOptions)

// 全选
const checkAll = ref(true)
// 不确定状态样式
const isIndeterminate = ref(false)

// 固定在左侧
const leftFixedOptions = computed(() => {
  return tableAllOptions.value.filter(item => item.fixed === 'left')
})
const leftFixedChecked = ref([])
watch(leftFixedOptions, (newOptions) => {
  leftFixedChecked.value = newOptions
    .filter(item => item.show === true)
    .map(item => item.label)
}, { deep: true, immediate: true })
const leftFixedOptionsShowAction = ref(
  Array.from({ length: leftFixedOptions.value.length }).fill(false),
)

// 不固定
const noFixedOptions = computed(() => {
  return tableAllOptions.value.filter(item => item.fixed === false)
})
const noFixedChecked = ref([])
watch(noFixedOptions, (newOptions) => {
  noFixedChecked.value = newOptions
    .filter(item => item.show === true)
    .map(item => item.label)
}, { deep: true, immediate: true })
const noFixedOptionsShowAction = ref(
  Array.from({ length: noFixedOptions.value.length }).fill(false),
)

// 固定在右侧
const rightFixedOptions = computed(() => {
  return tableAllOptions.value.filter(item => item.fixed === 'right')
})
const rightFixedChecked = ref([])
watch(rightFixedOptions, (newOptions) => {
  rightFixedChecked.value = newOptions
    .filter(item => item.show === true)
    .map(item => item.label)
}, { deep: true, immediate: true })
const rightFixedOptionsShowAction = ref(
  Array.from({ length: rightFixedOptions.value.length }).fill(false),
)

// 所有选中的多选框
const allChecked = computed(() => [
  ...leftFixedChecked.value,
  ...noFixedChecked.value,
  ...rightFixedChecked.value,
])

// 更新全选框的状态
function updateCheckAllStatus() {
  const allCheckedCount = allChecked.value.length
  const allOptionsCount = tableAllOptions.value.length
  if (allCheckedCount === allOptionsCount) {
    checkAll.value = true
    isIndeterminate.value = false
  } else if (allCheckedCount === 0) {
    checkAll.value = false
    isIndeterminate.value = false
  } else {
    isIndeterminate.value = true
  }
}

// 列展示操作
function handleCheckAllChange(val) {
  if (val) {
    tableAllOptions.value.forEach(item => item.show = true)
    emits('updateTableOptions', tableAllOptions.value)
  } else {
    tableAllOptions.value.forEach(item => item.show = false)
    emits('updateTableOptions', tableAllOptions.value)
  }
  isIndeterminate.value = false
}

function handleLeftFixedCheckedChange(value) {
  const selectedLabels = new Set(value)
  leftFixedOptions.value.forEach((item) => {
    item.show = selectedLabels.has(item.label)
  })
  tableAllOptions.value = [
    ...leftFixedOptions.value,
    ...noFixedOptions.value,
    ...rightFixedOptions.value,
  ]
  updateCheckAllStatus()
  emits('updateTableOptions', tableAllOptions.value)
}

function handleNoFixedCheckedChange(value) {
  const selectedLabels = new Set(value)
  noFixedOptions.value.forEach((item) => {
    item.show = selectedLabels.has(item.label)
  })
  tableAllOptions.value = [
    ...leftFixedOptions.value,
    ...noFixedOptions.value,
    ...rightFixedOptions.value,
  ]
  updateCheckAllStatus()
  emits('updateTableOptions', tableAllOptions.value)
}

function handleRightFixedCheckedChange(value) {
  const selectedLabels = new Set(value)
  rightFixedOptions.value.forEach((item) => {
    item.show = selectedLabels.has(item.label)
  })
  tableAllOptions.value = [
    ...leftFixedOptions.value,
    ...noFixedOptions.value,
    ...rightFixedOptions.value,
  ]
  updateCheckAllStatus()
  emits('updateTableOptions', tableAllOptions.value)
}
// 重置
function handleReset() {
  tableAllOptions.value = JSON.parse(JSON.stringify(props.initTableOptions))
  checkAll.value = true
  isIndeterminate.value = false

  emits('updateTableOptions', tableAllOptions.value)
}

// 鼠标移入action中显示
function handleMouseenter(type, index) {
  type[index] = true
}
function handleMouseLeave(type, index) {
  type[index] = false
}
// 不固定
function handleNoFixed(item) {
  tableAllOptions.value.forEach((options) => {
    if (options.label === item.label) {
      options.fixed = false
    }
  })
  emits('updateTableOptions', tableAllOptions.value)
}
// 固定到右侧
function handleRightFixed(item) {
  tableAllOptions.value.forEach((options) => {
    if (options.label === item.label) {
      options.fixed = 'right'
    }
  })
  emits('updateTableOptions', tableAllOptions.value)
}
// 固定到左侧
function handleLeftFixed(item) {
  tableAllOptions.value.forEach((options) => {
    if (options.label === item.label) {
      options.fixed = 'left'
    }
  })
  emits('updateTableOptions', tableAllOptions.value)
}
// 拖拽元素标签
const draggedLabel = ref(null)
// 开始推拽
function handleDragStart(label) {
  draggedLabel.value = label
}
function handleDrop(label) {
  if (draggedLabel.value !== null) {
    // tableAllOptions中对应的索引
    const allOptionsDraggedIndex = tableAllOptions.value.findIndex(
      item => item.label === draggedLabel.value,
    )
    const allOptionsTargetIndex = tableAllOptions.value.findIndex(
      item => item.label === label,
    )
    const temp = tableAllOptions.value[allOptionsDraggedIndex]
    tableAllOptions.value.splice(allOptionsDraggedIndex, 1)
    tableAllOptions.value.splice(allOptionsTargetIndex, 0, temp)
    draggedLabel.value = null
  }
}
</script>

<style scoped lang="scss">
.setting-popover {
  overflow: auto;
  max-height: 400px;
}

.content {
  .header {
    display: flex;
    justify-content: space-between;
  }

  .setting-list {
    display: flex;
    flex-direction: column;
    margin: 16px;

    .list {
      .el-checkbox {
        width: 100%;
      }

      :deep(.el-checkbox__label) {
        width: 100%;
      }

      &__item {
        display: flex;
        justify-content: space-between;

        .action {
          display: flex;
          gap: 10px;
          color: #000;

          i {
            font-size: 12px;
          }
        }
      }
    }
  }
}
</style>
